package com.esl.coordinator.command;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.esl.coordinator.exception.ImageSizeMismatchException;
import com.esl.coordinator.exception.STiTEQATMELIntegrationException;
import com.esl.coordinator.util.BMP;
import com.esl.coordinator.util.CRC;
import com.esl.coordinator.util.ESLCommandUtil;
import com.esl.coordinator.util.Hex;

public class LoadImageDataTransferCommand extends Command {
	static final Logger LOG = LoggerFactory
			.getLogger(LoadImageDataTransferCommand.class);

	public static final String LOAD_IMAGE_DATA_TRANSFER_LEAD_CODE = "CC";
	public static final String LOAD_IMAGE_DATA_TRANSFER_COMMAND_TYPE = "61";
	public static final int LOAD_IMAGE_DATA_TRANSFER_MESSAGE_LENGTH_PAD = 7;

	public static final int LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD = 16;
	public static final int LOAD_IMAGE_DATA_TRANSFER_MAX_MESSAGE_BYTES = 100;
	public static final int LOAD_IMAGE_DATA_TRANSFER_CHAR_BYTES = 2;

	public static final int LOAD_IMAGE_DATA_BMP_WIDTH = 172;
	public static final int LOAD_IMAGE_DATA_BMP_HEIGHT = 72;
	public static final int LOAD_IMAGE_DATA_MAX_BYTE_SIZE = LOAD_IMAGE_DATA_BMP_WIDTH
			* LOAD_IMAGE_DATA_BMP_HEIGHT / 8;

	private static final int EXPECTED_RESPONSE_BYTES = 11;

	private String macAddress;
	private byte[] imageBytes;

	public LoadImageDataTransferCommand(String macAddress, byte[] imageBytes,
			CommandReceiver commandClient) {
		super(commandClient, EXPECTED_RESPONSE_BYTES);
		this.macAddress = macAddress;
		this.imageBytes = imageBytes;

	}

	@Override
	public String[] buildCommand() throws STiTEQATMELIntegrationException {
		ArrayList<String> commands = new ArrayList<String>();
		// mac address to L, H hex bytes
		String lowMacByte = ESLCommandUtil.getMacLowByte(getMacAddress());
		String highMacByte = ESLCommandUtil.getMacHighByte(getMacAddress());

		String imageByteString = Hex.toHexString(getImageBytes());
		if (getImageBytes().length != LOAD_IMAGE_DATA_MAX_BYTE_SIZE) {
			throw new ImageSizeMismatchException(getImageBytes());
		}

		String splitImageBytes = null;
		int multiplier = LOAD_IMAGE_DATA_TRANSFER_MAX_MESSAGE_BYTES
				* LOAD_IMAGE_DATA_TRANSFER_CHAR_BYTES;
		for (int i = 1; i <= LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD; i++) {
			if (i != LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD) {
				splitImageBytes = imageByteString.substring((i - 1)
						* multiplier, multiplier * i);
			} else {
				splitImageBytes = imageByteString.substring((i - 1)
						* multiplier);
			}

			StringBuffer messageString = new StringBuffer();
			messageString.append(LOAD_IMAGE_DATA_TRANSFER_LEAD_CODE);

			int messageLength = splitImageBytes.length()
					/ LOAD_IMAGE_DATA_TRANSFER_CHAR_BYTES
					+ LOAD_IMAGE_DATA_TRANSFER_MESSAGE_LENGTH_PAD;
			messageString.append(Hex.toHexString(messageLength));
			messageString.append(LOAD_IMAGE_DATA_TRANSFER_COMMAND_TYPE);
			messageString.append(lowMacByte);
			messageString.append(highMacByte);
			messageString.append(Hex.toHexString(i)); // starts from 1
			messageString.append(Hex
					.toHexString(LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD));

			// split image bytes
			messageString.append(splitImageBytes);

			// append CRC results
			String imageBytesCRC = CRC.getCRC_CCITT_Kermit(splitImageBytes);
			messageString.append(imageBytesCRC);
			if (imageBytesCRC.length() == 2) {
				messageString.append("00");
			}

			commands.add(messageString.toString());
		}

		return commands.toArray(new String[commands.size()]);
	}

	@Override
	public boolean isCommandSuccessful() {
		int successCount = 0;
		if (getCommandResponse() != null
				&& getCommandResponse().length == LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD) {
			for (String commandResponse : getCommandResponse()) {
				if (commandResponse.charAt(14) == '0'
						&& commandResponse.charAt(0) == 'C') {
					successCount++;
				}
			}
		}
		return (successCount == LOAD_IMAGE_DATA_TRANSFER_TOTAL_RECORD);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof LoadImageDataTransferCommand) {
			return (((LoadImageDataTransferCommand) obj).getMacAddress()
					.equals(this.getMacAddress()));
		} else
			return false;
	}

	public String getMacAddress() {
		return macAddress;
	}

	public void setMacAddress(String macAddress) {
		this.macAddress = macAddress;
	}

	public byte[] getImageBytes() {
		return imageBytes;
	}

	public void setImageBytes(byte[] imageBytes) {
		this.imageBytes = imageBytes;
	}

	public static void main(String[] args) {
		Command testCmd;
		try {
			File file = new File("c:/App_Store_badge_0708-172x72.bmp");
			FileInputStream fis = new FileInputStream(file);
			byte[] bytes = IOUtils.toByteArray(fis);

			testCmd = STiTEQATMELCommandFactory.getInstance()
					.createLCDImageDataTransferCommand(
							"00-21-5C-00-0C-8A",
							BMP.toByteArrayNoPadding(bytes),
							SocketCommandReceiver
									.getInstance("localhost", 9999));
			CommandInvoker.sendCommand(testCmd);
			testCmd.isCommandSuccessful();
		} catch (FileNotFoundException e) {
			LOG.error("BMP file not found.", e);
		} catch (IOException e) {
			LOG.error("Could not read BMP file image.", e);
		} catch (STiTEQATMELIntegrationException e) {
			LOG.error("Error in test.", e);
		}
	}
}
